#include "qhostobjectmap.h"

#include "../../../libs/sharedLib/qabstracthost.h"
#include "../../../libs/sharedLib/qprojectcore.h"
#include "../../../libs/sharedLib/qabstractproperty.h"

#include <QVariant>
#include <QMetaObject>
#include <QMetaMethod>

using namespace CORELIB;

static int info_sort(const tagObjectInfo *p1, const tagObjectInfo *p2)
{

    return p1->m_name<p2->m_name;
}

QHostObjectMap::QHostObjectMap(SHAREDLIB::QAbstractProperty *property,SHAREDLIB::QAbstractHost *host)
{
    m_list=host->get_function_list();

    SHAREDLIB::QAbstractHost* top=SHAREDLIB::QProjectCore::getCore()->host();

    tagObjectInfo *info;

    QStringList list=property->attribute("param").toStringList();

    foreach(QString str,list)
    {
        if(check(str,&m_root))
        {
            info=new tagObjectInfo;
            info->m_host=NULL;
            info->m_name=str;
            info->m_parent=&m_root;
            m_root.m_children.append(info);
        }
    }

    info=make_info(host);
    info->m_name="self";
    info->m_parent=&m_root;
    m_root.m_children.append(info);

    if(host->getParent()!=NULL)
    {
        info=make_info(host->getParent());
        info->m_name="parent";
        info->m_parent=&m_root;
        m_root.m_children.append(info);
    }

    make_host(top,&m_root);
    make_host(host,&m_root);

    sort(m_root.m_children);
}

tagObjectInfo *QHostObjectMap::make_info(SHAREDLIB::QAbstractHost *host)
{
    tagObjectInfo *info=new tagObjectInfo;
    info->m_host=host;

    QList<SHAREDLIB::QAbstractHost*>    list=host->getChildren();

    foreach(SHAREDLIB::QAbstractHost* h,list)
    {
        tagObjectInfo *in=make_info(h);
        in->m_name=h->getPropertyValue("objectName").toString();
        if(check(in->m_name,info))
        {
            in->m_parent=info;
            info->m_children.append(in);
        }
        else
        {
            delete in;
        }
    }

    const QMetaObject *meta=host->metaObject();

    int count=meta->methodCount();
    for(int i=0;i<count;i++)
    {
        QMetaMethod method=meta->method(i);
        if(method.methodType()==QMetaMethod::Slot && method.access()==QMetaMethod::Public)
        {
            tagObjectInfo *in=new tagObjectInfo;
            QString str=method.signature();
            if(m_list.contains(str))
            {
                continue;
            }
            int index=str.indexOf("(");
            in->m_name=str.left(index);
            if(check(in->m_name,info))
            {
                in->m_host=NULL;
                in->m_method=method;
                in->m_parent=info;
                info->m_children.append(in);
            }
            else
            {
                delete in;
            }
        }
    }
    sort(info->m_children);
    return info;
}

void QHostObjectMap::make_host(SHAREDLIB::QAbstractHost *host, tagObjectInfo *info)
{
    QList<SHAREDLIB::QAbstractHost*> l=host->getChildren();
    info->m_host=host;
    foreach(SHAREDLIB::QAbstractHost* h,l)
    {
        tagObjectInfo *in=make_info(h);
        in->m_name=h->getPropertyValue("objectName").toString();
        if(check(in->m_name,info))
        {
            in->m_parent=info;
            info->m_children.append(in);
        }
        else
        {
            delete in;
        }
    }

    const QMetaObject *meta=host->metaObject();

    int count=meta->methodCount();
    for(int i=0;i<count;i++)
    {
        QMetaMethod method=meta->method(i);
        if(method.methodType()==QMetaMethod::Slot && method.access()==QMetaMethod::Public)
        {
            tagObjectInfo *in=new tagObjectInfo;
            QString str=method.signature();
            if(m_list.contains(str))
            {
                continue;
            }
            int index=str.indexOf("(");
            in->m_name=str.left(index);
            if(check(in->m_name,info))
            {
                in->m_parent=info;
                in->m_host=NULL;
                in->m_method=method;
                info->m_children.append(in);
            }
            else
            {
                delete in;
            }
        }
    }
}

QList<tagObjectInfo*>   QHostObjectMap::get_info(const QString &text)
{
    QStringList list=text.split(".");
    QList<tagObjectInfo*> ret;
    if(list.size()==0)
    {
        return ret;
    }



    tagObjectInfo *info=&m_root;
    for(int i=0;i<list.size()-1;i++)
    {
        info=get(info,list.at(i));
        if(info==NULL)
        {
            break;
        }
    }
    if(info==NULL)
    {
        return ret;
    }
    QList<tagObjectInfo*>   start_same;
    QList<tagObjectInfo*>   have_same;
    QString str;
    foreach(tagObjectInfo *in,info->m_children)
    {
        str=in->m_name.toLower();
        QString s=list.last().toLower();
        if(str.startsWith(s))
        {
            start_same.append(in);
        }
        else if(str.indexOf(list.last().toLower())>=0)
        {
            have_same.append(in);
        }
    }
    return start_same+have_same;

}

QList<tagObjectInfo*>   QHostObjectMap::get_info_same(const QString &text)
{
    if(text=="")
    {
        return m_root.m_children;
    }

    QStringList list=text.split(".");
    if(list.size()==0)
    {
        return QList<tagObjectInfo*>();
    }

    tagObjectInfo *info=&m_root;
    for(int i=0;i<list.size();i++)
    {
        if(list.at(i)=="")
        {
            continue;
        }
        info=get(info,list.at(i));
        if(info==NULL)
        {
            break;
        }
    }
    if(info==NULL)
    {
        return QList<tagObjectInfo*>();
    }
    else
    {
        return info->m_children;
    }
}

tagObjectInfo *QHostObjectMap::get(tagObjectInfo *info, const QString &name)
{
    foreach(tagObjectInfo *in,info->m_children)
    {
        if(in->m_name==name)
        {
            return in;
        }
    }

    return NULL;
}

bool QHostObjectMap::check(const QString &name, tagObjectInfo *info)
{
    foreach(tagObjectInfo* in,info->m_children)
    {
        if(in->m_name==name)
        {
            return false;
        }
    }
    return true;
}

void QHostObjectMap::sort(QList<tagObjectInfo *> &list)
{
    qSort(list.begin(),list.end(),info_sort);
}
